import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_again/models/video_info.dart';
import 'package:flutter_again/models/video_platform.dart';
import 'package:flutter_again/services/video_platform_manager.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import '../models/video_search_params.dart';
import '../widgets/item_video.dart';
import 'package:flutter_again/utils/log.dart';

class VideoPage extends StatefulWidget {
  const VideoPage({super.key});

  @override
  State<VideoPage> createState() => _VideoPage();
}

class _VideoPage extends State<VideoPage> {
  final VideoSearchParams params = VideoSearchParams(query: '', page: 1);
  late VideoPlatformManager platformManager;
  final TextEditingController inputController = TextEditingController();
  final _scrollController = ScrollController();
  final _focusNode = FocusNode();
  final allToken = 'all';
  String platformId = '';

  List<VideoInfo> list = [];
  bool isLoading = false;
  bool searchShow = true;
  bool hasNextPage = false;

  String? get realPlatformId {
    return platformId == allToken ? null : platformId;
  }

  VideoPlatform? get platformInfo {
    final id = realPlatformId;
    if (id == null) return null;
    return platformManager.getPlatformInfo(id);
  }

  List<String>? get supportedCategories {
    final curPlatformInfo = platformInfo;
    if (curPlatformInfo == null) return null;
    return curPlatformInfo.supportedCategories;
  }

  List<String>? get supportedLocations {
    final curPlatformInfo = platformInfo;
    if (curPlatformInfo == null) return null;
    return curPlatformInfo.supportedLocations;
  }

  List<String>? get supportedYears {
    final curPlatformInfo = platformInfo;
    final minYear = curPlatformInfo?.minYear;
    final maxYear = curPlatformInfo?.maxYear;
    if (curPlatformInfo == null || minYear == null || maxYear == null) return null;
    List<String> list = [];
    for (var i = minYear; i <= maxYear; i++) {
      list.add(i.toString());
    }
    return list;
  }

  Map<String, List<String>> get menuMap {
    Map<String, List<String>> map = {};
    final categories = supportedCategories;
    final locations = supportedLocations;
    final years = supportedYears;
    if (categories != null) {
      map['category'] = ['全部', ...categories];
    }
    if (locations != null) {
      map['location'] = ['全部', ...locations];
    }
    if (years != null) {
      map['year'] = ['全部', ...years];
    }
    return map;
  }

  void changeMenu(String menuProp, String? value) {
    String? realVal = value == '全部' ? null : value; 
    switch(menuProp) {
      case 'category':
        params.category = realVal;
        break;
      case 'location':
        params.location = realVal;
        break;
      case 'year':
        params.year = realVal;
        break;
    }
    onSearch();
  }

  String getMenuName(String? prop) {
    return prop ?? '全部';
  }

  List<Map<String, String>> get platformList {
    final manager = context.watch<VideoPlatformManager>();
    List<Map<String, String>> list = [
      {'label': '全部', 'value': allToken},
      ...manager.getAllPlatforms().map((item) {
        return {'label': item.name, 'value': item.id};
      }),
    ];
    return list;
  }

  @override
  void initState() {
    super.initState();
    platformManager = context.read<VideoPlatformManager>();
    platformId = allToken;
    onSearch();
    _scrollController.addListener(() {
      final maxOffset = _scrollController.position.maxScrollExtent;
      final curPixels = _scrollController.position.pixels;
      final direct = _scrollController.position.userScrollDirection;
      unfocusInput();
      if (curPixels > maxOffset - 100) {
        loadMore();
      }
      if (searchShow && direct == ScrollDirection.reverse) {
        setState(() {
          searchShow = false;
        });
      }
    });
  }

  @override
  void activate() {
    super.activate();
    log.d('video_page activate');
  }

  @override
  void deactivate() {
    super.deactivate();
  }

  @override
  void didChangeDependencies() {
    log.d('video_page didChangeDependencies');
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(covariant VideoPage oldWidget) {
    log.d('video_page didUpdateWidget');
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _scrollController.dispose();
    _focusNode.dispose();
    super.dispose();
  }

  void unfocusInput() {
    if (_focusNode.hasFocus) {
      _focusNode.unfocus();
    }
  }

  void scrollToTop() {
    _scrollController.animateTo(
      0,
      duration: Durations.medium1,
      curve: Curves.easeInOut,
    );
  }

  Future<void> onSearch([int page = 1]) async {
    if (isLoading) return;
    isLoading = true;
    params.query = inputController.value.text;
    params.page = page;
    try {
      final data = await platformManager.search(
        params,
        platformId: realPlatformId,
      );
      List<VideoInfo> pageList;
      params.page = data.currentPage;
      hasNextPage = data.hasNextPage;
      if (data.currentPage == 1) {
        pageList = data.videos;
      } else {
        pageList = [...list, ...data.videos];
      }
      setState(() {
        list = pageList;
        if (data.currentPage == 1) {
          scrollToTop();
        }
      });
    } catch (err) {
      /** empty */
    }
    isLoading = false;
  }

  void toDetail(String? id) async {
    if (id == null) return;
    var videoInfo = list.firstWhere((item) => item.id == id);
    unfocusInput();
    var newVideoInfo = await platformManager.getVideoDetail(
      videoInfo.platform,
      videoInfo.id,
    );
    
    final videoUrl = newVideoInfo?.videoUrl;
    final videoSeqsList = newVideoInfo?.videoSeqs?.map((item) {
      return { 'title': item.title, 'url': item.url };
    }).toList();
    final seqLinksStr = videoSeqsList != null ? jsonEncode(videoSeqsList) : '';
    final num = videoSeqsList != null ? '1' : null;
    if (videoUrl != null && mounted) {
      context.pushNamed(
        'videoPlayer',
        queryParameters: {'title': videoInfo.title, 'url': videoUrl, 'seqLinks': seqLinksStr, 'platformId': videoInfo.platform, 'num': num},
      );
    }
  }

  Future<void> loadMore() async {
    if (isLoading) return;
    final page = params.page;
    if (hasNextPage) {
      log.d('加载第${page + 1}页');
      await onSearch(page + 1);
      log.d('已加载完成第${page + 1}页');
    }
  }

  @override
  Widget build(BuildContext context) {
    final menuWidgets = menuMap.keys.map((menuProp) {
      final menu = menuMap[menuProp]!;
      return Expanded(
        child: DropdownMenu<String>(
          onSelected:(value) {
            changeMenu(menuProp, value);
          },
          initialSelection: menuProp == 'category' ? getMenuName(params.category) : menuProp == 'location' ? getMenuName(params.location) : getMenuName(params.year),
          label: Text(menuProp.substring(0, 3)),
          dropdownMenuEntries: menu.map((item) {
            return DropdownMenuEntry(value: item, label: item);
          }).toList(),
        ),
      );
    }).toList();
    
    return Scaffold(
      body:  SafeArea(
        child: Column(
          children: [
            // 搜索框
            Visibility(
              visible: searchShow,
              child: Container(
                height: 78,
                decoration: BoxDecoration(
                  border: BoxBorder.fromLTRB(
                    bottom: BorderSide(
                      width: 1,
                      color: Color.fromRGBO(0, 0, 0, 0.2),
                    ),
                  ),
                ),
                padding: EdgeInsetsDirectional.all(10),
                child: Row(
                  spacing: 10,
                  children: [
                    SizedBox(
                      width: 120,
                      height: 58,
                      child: DropdownMenu<String>(
                        onSelected: (String? value) {
                          setState(() {
                            platformId = value ?? '';
                          });
                        },
                        label: const Text('platform'),
                        initialSelection: platformId,
                        dropdownMenuEntries: platformList.map((item) {
                          final label = item['label'] ?? '';
                          final value = item['value'] ?? '';
                          return DropdownMenuEntry(value: value, label: label);
                        }).toList(),
                      ),
                    ),
                    Expanded(
                      child: TextField(
                        controller: inputController,
                        focusNode: _focusNode,
                        onChanged: (value) {
                          onSearch();
                        },
                        decoration: InputDecoration(
                          border: OutlineInputBorder(
                            borderSide: BorderSide(
                              color: Color.fromRGBO(0, 0, 0, 0.5),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            // 类别选择
            Visibility(
              visible: menuWidgets.isNotEmpty && searchShow,
              child: Container(
                height: 78,
                decoration: BoxDecoration(
                  border: BoxBorder.fromLTRB(
                    bottom: BorderSide(
                      width: 1,
                      color: Color.fromRGBO(0, 0, 0, 0.2),
                    ),
                  ),
                ),
                padding: EdgeInsetsDirectional.all(10),
                child: Row(
                  spacing: 10,
                  children: menuWidgets,
                ),
              ),
            ),
            Expanded(
              child: Padding(
                padding: EdgeInsetsGeometry.all(15),
                child: RefreshIndicator(
                  triggerMode: RefreshIndicatorTriggerMode.onEdge,
                  edgeOffset: 20,
                  onRefresh: onSearch,
                  child: ListView.builder(
                    itemCount: list.length,
                    controller: _scrollController,
                    itemBuilder: (context, index) {
                      var item = list[index];
                      return ItemVideo(
                        id: item.id,
                        thumbnailUrl: item.thumbnailUrl,
                        title: item.title,
                        subtitle: '${item.year ?? ''} - ${item.label ?? ''}',
                        onTap: toDetail,
                      );
                    },
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: IconButton(
        onPressed: () {
          setState(() {
            searchShow = !searchShow;
          });
        },
        icon: Icon(Icons.circle, color: searchShow ? Colors.orange : Colors.lightGreen, size: 40,)
      )
    );
  }
}
